//
//  audio_test_interface.m
//  thunder_framework
//
//  Created by Cloud on 10-11-10.
//  Copyright 2010 Thunder Network Ltd. All rights reserved.
//

#import "ios_audio_service_impl.h"
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioToolbox/AudioFile.h>
#import <OpenAL/al.h>
#import <OpenAL/alc.h>	
#import <MediaPlayer/MPMusicPlayerController.h>
#import "audio_service.h"
#include "ekk_interface.h"

// 设置buffer size
#define AUDIO_SERVICE_BUFFERS_NUM 10
// 最大buffer_size
#define MAX_AUDIO_SERVICE_BUFFERS_NUM 100	

static ALCdevice *g_device = NULL;
static ALCcontext *g_context = NULL;
float  m_play_speed = 1.0;
static float g_simulator_vol = 1.f;

// ---------------------------------------------------------------------
// 实现声音播放的类声明
@interface audio_service_impl : NSObject
{	
	unsigned int *m_buffers;
	long long m_ts[MAX_AUDIO_SERVICE_BUFFERS_NUM];
	unsigned int m_source;
	unsigned int m_used_buffer;	// 已经用掉的buffer
	unsigned int m_head;
	unsigned int m_tail;
	unsigned int m_render_flag;
	unsigned int m_len;
	long m_frequency;	// frequency
	long m_curfrequency;
	long m_channels;	// channels
	long m_bits;	// bits
	long m_volume;
	long m_format;	// AL_FORAMT_...
	long m_total_buffers;	// 申请到的总的buffer数
}

//- (id) openAudioFile:(NSString*)filePath;
//- (UInt32) audioFileSize:(AudioFileID) fileDescriptor;
- (long) play_audio_buffer:(unsigned char *) buffer withLength:(long) length withTs:(long long) ts;
- (bool) is_playing;
- (bool) check_error;	// 检查是否有错误
- (long) replay;
- (long) pause;
- (long) empty_buffer_queue;	// 清空buffer queue
- (long) set_volume:(long) volume;
// 返回声音
- (long) get_volume;
- (void) set_format;	// 设置format

// 访问成员变量
- (long) get_frequency;
- (long long) get_ts;
- (long) get_frame_count;
- (long) get_channels;
- (long) get_bits;

- (long) set_play_speed:(float) play_speed;
- (void) set_frequency:(long) frequency;
- (void) set_channels:(long) channels;
- (void) set_bits:(long) bits;

@end
// ---------------------------------------------------------------------


// ---------------------------------------------------------------------
// 实现声音播放的类定义
@implementation audio_service_impl

- (id) init:(long) frequency withChannels:(long) channels withBits:(long) bits
{
	// initial from the param
	if (0 == frequency)
		frequency = 44100;
	m_frequency = frequency;
	m_curfrequency = m_frequency;
	if (1 != channels && 2 != channels)
		channels = 1;
	m_channels = channels;
	if (8 != bits && 16 != bits)
		bits = 16;
	m_bits = bits;
	
	// 声音先设为最大
	m_volume = 100;
	
	// 计算format
	[self set_format];
	
	m_used_buffer = 0;
	m_source = 0;
	m_head = 0;
	m_tail = 0;
	m_render_flag = 0;
	
	// 初次分配AUDIO_SERVICE_BUFFERS_NUM个buffer，如果不够再成倍扩张buffers
	m_total_buffers = MAX_AUDIO_SERVICE_BUFFERS_NUM;
	m_buffers = ekk_malloc(m_total_buffers * sizeof(unsigned int));
	if (!m_buffers)
		return NULL;
	
	for (long i = 0; i < m_total_buffers; i++)
		m_buffers[i] = 0;
	
	// generate the buffers and sources
	alGetError(); // clear error state
	alGenBuffers(m_total_buffers, m_buffers);	
	if (![self check_error])
		return NULL;

	alGetError();
	alGenSources(1, &m_source);
	if (![self check_error])
		return NULL;
	
//	alSourcef(m_source, AL_PITCH, 1.0f);
//	alSourcef(m_source, AL_GAIN, 1.0f);
//	alSource3f(m_source, AL_POSITION, 0.0f, 0.0f, 0.0f);
//	alSource3f(m_source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
//	alSource3f(m_source, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
//	alSourcef(m_source, AL_ROLLOFF_FACTOR, 0.0f);
//	alSourcei(m_source, AL_SOURCE_RELATIVE, AL_TRUE);
	
	if (![self check_error])
		return NULL;
		
	return self;
}

- (void) release_processed_buffers
{	
	long processed_buffer_num = 0;
//	printf("release_processed_buffers \n");
	alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &processed_buffer_num);
	if (![self check_error])
	{
//		printf("release_processed_buffers error \n");
		return ;
	}
//	printf("release_processed_buffers processed_buffer_num = %d\n",
//		processed_buffer_num);

	if (0 == processed_buffer_num)
	{
		return;
	}

	ALuint *processed_buffer_names = NULL;
	processed_buffer_names = ekk_malloc(sizeof(ALuint) * processed_buffer_num);
	if (!processed_buffer_names)				
		return ;			
	ekk_memset((void *)processed_buffer_names, 0, processed_buffer_num);						
	// ɵbuffer			
	alSourceUnqueueBuffers(m_source, processed_buffer_num, processed_buffer_names);	
	if (![self check_error])
	{
		ekk_free((void *)processed_buffer_names);
		return ;	
	}
	ekk_free((void *)processed_buffer_names);
	m_tail += processed_buffer_num;
	m_tail = m_tail % MAX_AUDIO_SERVICE_BUFFERS_NUM;
	m_render_flag = 1;
	long queued_buffers = 0;
	alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued_buffers);
	if (![self check_error])
		return 1;
	
//	printf("release_processed_buffers m_head = %d,m_tail = %d,queued_buffers = %d \n",
//			m_head,m_tail,queued_buffers);

//	printf("release_processed_buffers processed_buffer_num = %d,m_tail = %d\n",
//			processed_buffer_num,m_tail);
}

- (void) dealloc
{
	[self empty_buffer_queue];
	
	alDeleteSources(1, &m_source);
	alDeleteBuffers(m_total_buffers, m_buffers);
	
	ekk_free((void *)m_buffers);

	[super dealloc];
}

// open the audio file  
// returns a big audio ID struct 
//- (id) openAudioFile:(NSString*)filePath
//{
//    AudioFileID outAFID;    
//    // use the NSURl instead of a cfurlref cuz it is easier     
//    NSURL * afUrl = [NSURL fileURLWithPath:filePath]; 
//    // do some platform specific stuff..  
//#if TARGET_OS_IPHONE    
//    OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, kAudioFileReadPermission, 0, &outAFID);  
//#else   
//    OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, fsRdPerm, 0, &outAFID);  
//#endif      
//    if (result != 0) 
//        NSLog(@"cannot openf file: %@",filePath);   
//    
//    return outAFID; 	
//}
//
//-(UInt32) audioFileSize:(AudioFileID) fileDescriptor
//{
//	UInt64 outDataSize = 0;     
//    UInt32 thePropSize = sizeof(UInt64);    
//    OSStatus result = AudioFileGetProperty(fileDescriptor, kAudioFilePropertyAudioDataByteCount, &thePropSize, &outDataSize);   
//    if(result != 0) 
//        NSLog(@"cannot find file size");    
//	
//	return (UInt32)outDataSize;  
//}

- (long) play_audio_buffer:(unsigned char *) buffer withLength:(long) length withTs:(long long) ts
{	
//	printf("play_audio_buffer ts = %llu\n",ts);
	[self release_processed_buffers];

//	printf("play_audio_buffer m_curfrequency = %d,m_frequency = %d\n",m_curfrequency,m_frequency);
	// 
	alBufferData(m_buffers[m_head], m_format, (const ALvoid* )buffer, (ALsizei)length, m_curfrequency);
	if (![self check_error])
	{
//		printf("play_audio_buffer error 216 \n");
		return 1;
	}
	// 
	alSourceQueueBuffers(m_source, 1, &(m_buffers[m_head]));
	if (![self check_error])
	{
//		printf("play_audio_buffer error 223 \n");
		return 1;
	}
	
	m_ts[m_head] = ts;
		
	m_head++;

	m_head = m_head % MAX_AUDIO_SERVICE_BUFFERS_NUM;

	long queued_buffers = 0;
	alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued_buffers);
	if (![self check_error])
		return 1;
	
//	printf("play_audio_buffer m_head = %d,m_tail = %d,queued_buffers = %d \n",
//			m_head,m_tail,queued_buffers);

	if (![self is_playing])
		alSourcePlay(m_source);	
#if 0
	if (![self is_playing])
	{
		[self empty_buffer_queue];
		alSourcePlay(m_source);	
		if (![self is_playing])
		{
			printf("play_audio_buffer play fail !\n");
		}
	}
#endif

	return 0;
#if 0
	// 已经有buffer排队时
	if (m_used_buffer != 0)
	{
		// 首先查询当前队列中的状态
		long queued_buffers = 0;
		alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued_buffers);
		if (![self check_error])
			return 1;
		long processed_buffers = 0;
		alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &processed_buffers);
		if (![self check_error])
			return 1;
		
		// 如果所有排队的buffer均用完，那么弹出所有，变成初始状态
		if(queued_buffers == processed_buffers)
		{
			long long cur_time = 0;   
			struct timeval tv;
			if(gettimeofday(&tv,NULL)==0)		
				cur_time =  tv.tv_sec * 1000000 + tv.tv_usec;

			// 弹出所有的buffer
			ALuint *used_buffer_names = NULL;
			used_buffer_names = ekk_malloc(sizeof(ALuint) * queued_buffers);
			if (!used_buffer_names)
				return 1;
			ekk_memset((void *)used_buffer_names, 0, queued_buffers);
			
			// 弹出旧的buffer
			alSourceUnqueueBuffers(m_source, queued_buffers, used_buffer_names);
			if (![self check_error])
				return 1;
			ekk_free((void *)used_buffer_names);
			m_used_buffer = 0;
			
			// 将排队的buffer数和处理的 buffer数都置零
			queued_buffers = 0;
			processed_buffers = 0;
		}
		
		// 检查这几个buffers是否用完,没用完就用这些空着的buffer
		if (m_used_buffer < m_total_buffers)
		{
			// 将bufferID索引所代表的缓冲区填充数据
			alBufferData(m_buffers[m_used_buffer], m_format, (const ALvoid* )buffer, (ALsizei)length, m_frequency);
			if (![self check_error])
				return 1;
			
			// 将buffer排队
			alSourceQueueBuffers(m_source, 1, &(m_buffers[m_used_buffer]));
			if (![self check_error])
				return 1;
			
			m_used_buffer++;
		}
		
		// 所有的buffer全部加到队列中则查找放完的buffer
		else 
		{
			/*		// test cloud
			 printf("\n%d buffers processed, %d total buffers\n", val, m_total_buffers);
			 alGetSourcei(m_source, AL_BUFFERS_QUEUED, &val);
			 printf("%d buffers queued, %d total buffers\n", val, m_total_buffers);
			 
			 alGetSourcei(m_source, AL_SOURCE_STATE, &val);
			 switch (val) {
			 case AL_INITIAL:
			 //				printf("source state: INITIAL\n");
			 break;
			 case AL_PLAYING:
			 //				printf("source state: PLAYING\n");
			 break;
			 case AL_PAUSED:
			 //				printf("source state: PAUSED\n");
			 break;
			 case AL_STOPPED:
			 printf("source state: STOPPED\n");
			 break;
			 default:
			 break;
			 }
			 int a = 0;
			 if (0 == a)
			 return NULL;
			 alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &val);
			 // test cloud*/
			
			// 如果所有的buffer全部用完，并且在控制的buffer数目内，那么重新产生新的buffers
			if (processed_buffers <= 0)
			{
				// 重新分配m_total_buffers + AUDIO_SERVICE_BUFFERS_NUM个buffer
				unsigned int *temp_buffer = NULL;
				temp_buffer = ekk_malloc((m_total_buffers + AUDIO_SERVICE_BUFFERS_NUM)  * sizeof(unsigned int));
				if (!temp_buffer)
					return 1;
				// 限制buffer 大小的增长
				if (queued_buffers >= MAX_AUDIO_SERVICE_BUFFERS_NUM )
				{
					printf("error queued_buffers full !\n");
					return 1;
				}
				
				// 新的buffers位于后面AUDIO_SERVICE_BUFFERS_BUM
				alGetError(); // clear error state
				alGenBuffers(AUDIO_SERVICE_BUFFERS_NUM, (temp_buffer + m_total_buffers));	
				if (![self check_error])
					return 1;
				
				// 将之前的buffer全部拷到temp_buffer的前m_total_buffers个位置
				for (long i = 0; i < m_total_buffers; i++)
					temp_buffer[i] = m_buffers[i];
				
				// 释放掉之前的buffers内存，将m_buffers指向刚刚生成的buffers
				ekk_free((void *)m_buffers);
				m_buffers = temp_buffer;
				
				// 将bufferID索引所代表的缓冲区填充数据
				alBufferData(m_buffers[m_used_buffer], m_format, (const ALvoid* )buffer, (ALsizei)length, m_frequency);
				if (![self check_error])
					return 1;
				
				// 将buffer排队
				alSourceQueueBuffers(m_source, 1, &(m_buffers[m_used_buffer]));			
				if (![self check_error])
					return 1;
				
				m_used_buffer++;
				
				// 总的buffers数目增加
				m_total_buffers += AUDIO_SERVICE_BUFFERS_NUM;
				
				// test cloud
				//printf("%d buffers processed, %d buffers queued, %d total buffers\n", processed_buffers, queued_buffers + 1, m_total_buffers);
				// test cloud end
			}
			
			// 有processed buffer, 直接弹出一个，然后装入新的数据
			else {
				long used_buffer = 0;
				// 弹出旧的buffer
				alSourceUnqueueBuffers(m_source, 1, &used_buffer);
				if (![self check_error])
					return 1;
				// 装入数据
				alBufferData(used_buffer, m_format, (const ALvoid* )buffer, (ALsizei)length, m_frequency);
				if (![self check_error])
					return 1;
				// 加入队列
				alSourceQueueBuffers(m_source, 1, &used_buffer);
				if (![self check_error])
					return 1;

			}
		}
		
	}
	
	// 初始状态, m_used_buffer = 0
	else 
	{
		// 将bufferID索引所代表的缓冲区填充数据
		alBufferData(m_buffers[0], m_format, (const ALvoid* )buffer, (ALsizei)length, m_frequency);
		if (![self check_error])
			return 1;
		
		// 将buffer排队
		alSourceQueueBuffers(m_source, 1, &(m_buffers[m_used_buffer]));
		if (![self check_error])
			return 1;
		
		// test cloud
#ifdef DEBUG
		//printf("%d used buffers, %d total buffers\n", m_used_buffer, m_total_buffers);
#endif
		
		m_used_buffer = 1;
	}
	
	
	// 播放声音
	if (![self is_playing])
		alSourcePlay(m_source);	
	
	return 0;
#endif
}

// 是否正在play
- (bool) is_playing
{
	ALenum val;
	alGetSourcei(m_source, AL_SOURCE_STATE, &val);
	if (![self check_error])
		return FALSE;
	return (AL_PLAYING == val);
}

// 检查是否有错误
- (bool) check_error
{
	long error = alGetError();
	switch (error)
	{
	case AL_NO_ERROR:
		return TRUE;
	case AL_INVALID_NAME:
		NSLog(@"Invalid name passed\n");
		return FALSE;
	case AL_INVALID_ENUM:
		NSLog(@"Invalid enum was passed\n");
		return FALSE;
	case AL_INVALID_VALUE:
		NSLog(@"Invalid buffer value\n");
		return FALSE;
	case AL_INVALID_OPERATION: 
		NSLog(@"The requested operation is no valid\n");
		return FALSE;
	case AL_OUT_OF_MEMORY:
		NSLog(@"Not enough memory\n");
		return FALSE;
	default:
		return FALSE;
	}
}

- (long)replay
{
	if ([self is_playing])
	{
		return 0;
	}
//	printf("replay...\n");
	alSourcePlay(m_source);
#if 0
	if (![self is_playing])
	{
		[self empty_buffer_queue];
		alSourcePlay(m_source);	
		if (![self is_playing])
		{
			printf("replay play fail !\n");
		}
	}
#endif
	return 0;
}
- (long)pause
{
	if ([self is_playing])
	{
//		printf("pause...\n");
		alSourcePause(m_source);
		return 0;
	}
	return 0;
}

// 清空buffer queue
- (long) empty_buffer_queue
{
//	if ([self is_playing])
		alSourceStop(m_source);
	ekk_sleep(50 * 1000);
	long queued = 0;
	alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued);
	if (![self check_error])
		return 1;
	
	// cloud test
#ifdef DEBUG
//	printf("\n%d queued buffers, %d total_buffers\n", queued, m_total_buffers);
#endif
	// cloud test
	
	// 弹出所有的buffer
	ALuint *used_buffer_names = NULL;
	used_buffer_names = ekk_malloc(sizeof(ALuint) * queued);
	if (!used_buffer_names)
		return 1;
	ekk_memset((void *)used_buffer_names, 0, queued);
	
	// 弹出旧的buffer
	alSourceUnqueueBuffers(m_source, queued, used_buffer_names);
//	alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued);
	if (![self check_error])
	{
		ekk_free((void *)used_buffer_names);
		return 1;
	}

	ekk_free((void *)used_buffer_names);
	

	if (![self check_error])
		return 1;
	
	m_used_buffer = 0;
//	ekk_memset(m_buffers, 0, m_total_buffers * sizeof(unsigned int));
	ekk_memset(m_ts, -1, MAX_AUDIO_SERVICE_BUFFERS_NUM * sizeof(long long));

	m_head = 0;
	m_tail = 0;
	m_render_flag = 0;

	long queued_buffers = 0;
	alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued_buffers);
	if (![self check_error])
		return 1;
	
//	printf("empty_buffer_queue m_head = %d,m_tail = %d,queued_buffers = %d \n",
//			m_head,m_tail,queued_buffers);
	
	return 0;
}

// 设置声音
- (long) set_volume:(long) volume
{
	// 限定volume范围
	volume = volume < 0 ? 0 : (volume > 100 ? 100 : volume);
	// 传进来的声音范围是[0, 100],转化为[0.0f, 1.0f]
	alSourcef(m_source, AL_GAIN, volume / 100.0f);	
	if (![self check_error])
		return 1;
	else 
	{
		m_volume = volume;
		return 0;
	}
}

// 返回声音
- (long) get_volume
{		
	return m_volume;
}

// 设置format
- (void) set_format
{
	if (8 == m_bits)
	{
		if (1 == m_channels)
			m_format = AL_FORMAT_MONO8;
		else if (2 == m_channels)
			m_format = AL_FORMAT_STEREO8;
	}
	
	else if (16 == m_bits)
	{
		if (1 == m_channels)
			m_format = AL_FORMAT_MONO16;
		else if (2 == m_channels)
			m_format = AL_FORMAT_STEREO16;
	}
	
	// 其它都用单声道16位表示
	else 
		m_format = AL_FORMAT_MONO16;
}

// 访问成员变量
- (long) get_frequency
{
	return m_curfrequency;
}

- (long) get_channels
{
	return m_channels;
}

- (long) get_bits
{
	return m_bits;
}

- (long long) get_ts
{
	[self release_processed_buffers];

	long long ts = 0;

	if (0 == m_render_flag)
	{
		ts = m_ts[0];
	}
	else
	{
		if (0 == m_tail)
		{
			ts = m_ts[MAX_AUDIO_SERVICE_BUFFERS_NUM-1];
		}
		else
		{
			ts = m_ts[m_tail-1];
		}
	}

	long queued_buffers = 0;
	alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued_buffers);
	if (![self check_error])
		return 1;

	//printf("ts = %llu,m_tail = %d,m_head = %d,queued_buffers = %d\n",
		//ts,m_tail,m_head,queued_buffers);
	return ts;
}

- (long) get_frame_count
{
	long queued_buffers = 0;
	long processed_buffers = 0;
	long frame_count = 0;
	alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued_buffers);
	if (![self check_error])
		return 1;
	alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &processed_buffers);
	if (![self check_error])
		return 1;
	
//	printf("get_frame_count queued_buffers = %d,processed_buffers = %d\n",
//		queued_buffers,processed_buffers);
//	
	frame_count = queued_buffers-processed_buffers;
	
	return frame_count;
}
- (long) get_play_state
{
	ALenum val;
	int play_state = 0;

	alGetSourcei(m_source, AL_SOURCE_STATE, &val);
	
		
					

	
					

	if (AL_PLAYING == val)
	{
		play_state = 1;
	}
	else
	{
		play_state = 0;
	}
	return play_state;
}

- (void) set_frequency:(long) frequency
{
	
//	if (m_frequency != 0 && m_frequency == frequency)
//		return;
	if (0 == frequency)
		frequency = 44100;
	m_frequency = frequency;
	if ((0.0 >= m_play_speed) || (m_play_speed > 2.0))
	{
		m_play_speed = 1.0;
	}
	m_curfrequency = m_frequency*m_play_speed;

//	printf("set_frequency frequency = %d,m_play_speed = %f,m_curfrequency = %d\n",
//		frequency,m_play_speed,m_curfrequency);
}

- (long) set_play_speed:(float) play_speed
{
	m_play_speed = play_speed;
	if ((0 >= m_play_speed) || (m_play_speed > 2))
	{
		m_play_speed = 1;
	}
	m_curfrequency = m_frequency*m_play_speed;
//	printf("set_play_speed m_play_speed = %f,m_curfrequency = %d,m_frequency = %d\n",
//			m_play_speed,m_curfrequency,m_frequency);
}

- (void) set_channels:(long) channels
{
	if (m_channels != 0 && m_channels == channels)
		return;
	if (1 != channels && 2 != channels)
		channels = 1;
	m_channels = channels;
}

- (void) set_bits:(long) bits
{
	if (m_bits != 0 && m_bits == bits)
		return;
	if (8 != bits && 16 != bits)
		bits = 16;
	m_bits = bits;
}

@end
// ---------------------------------------------------------------------

// ---------------------------------------------------------------------
// 实现audio service接口

void create_audio_service_impl(void** audio_service_data, long samplerate, long channels, long bitspersample)
{
//	printf("create_audio_service_impl \n");

	audio_service_impl *audio = [[audio_service_impl alloc] init:samplerate withChannels:channels withBits:bitspersample];
	(*audio_service_data) = (void *)audio;
}

long destroy_audio_service_impl(void* audio_service_data)
{
//	printf("destroy_audio_service_impl \n");

	if (NULL != audio_service_data)
		[(audio_service_impl *)(audio_service_data) release];
	
	return 0;
}

long get_audio_service_samplerate_impl(void* audio_service_data)
{
//	printf("get_audio_service_samplerate_impl \n");

	return [(audio_service_impl *)(audio_service_data) get_frequency];
}

long get_audio_service_channels_impl(void* audio_service_data)
{
	return [(audio_service_impl *)(audio_service_data) get_channels];
}

long get_audio_service_bitspersample_impl(void* audio_service_data)
{
//	printf("get_audio_service_bitspersample_impl \n");

	return [(audio_service_impl *)(audio_service_data) get_bits];
}

float get_audio_service_volume_impl()
{
#if TARGET_IPHONE_SIMULATOR
    return g_simulator_vol;
#else
	return [MPMusicPlayerController applicationMusicPlayer].volume;
#endif
}

long long get_audio_service_ts_impl(void* audio_service_data)
{
//	printf("get_audio_service_ts_impl \n");

	return [(audio_service_impl *)(audio_service_data) get_ts];
}

long get_audio_service_frame_count_impl(void* audio_service_data)
{
//	printf("get_audio_service_frame_count_impl \n");

	return [(audio_service_impl *)(audio_service_data) get_frame_count];
}

long get_audio_service_play_state_impl(void* audio_service_data)
{
	return [(audio_service_impl *)(audio_service_data) get_play_state];
}


void set_audio_service_samplerate_impl(void* audio_service_data, long samplerate)
{
//	printf("set_audio_service_samplerate_impl samplerate = %d\n",samplerate);

	[(audio_service_impl *)(audio_service_data) set_frequency:samplerate];
	// 设置完后重新计算format
	[(audio_service_impl *)(audio_service_data) set_format];
}

void set_audio_service_channels_impl(void* audio_service_data, long channels)
{
//	printf("set_audio_service_channels_impl \n");

	[(audio_service_impl *)(audio_service_data) set_channels:channels];
	// 设置完后重新计算format
	[(audio_service_impl *)(audio_service_data) set_format];
}

void set_audio_service_bitspersample_impl(void* audio_service_data, long bitspersample)
{
//	printf("set_audio_service_bitspersample_impl \n");

	[(audio_service_impl *)(audio_service_data) set_bits:bitspersample];
	// 设置完后重新计算format
	[(audio_service_impl *)(audio_service_data) set_format];
}

void set_audio_service_volume_impl(float volume)
{
#if TARGET_IPHONE_SIMULATOR
    volume = volume > 1.0f ? 1.0f : (volume < 0.f ? 0.f : volume);
    g_simulator_vol = volume;
#else
	[[MPMusicPlayerController applicationMusicPlayer] setVolume:volume];
#endif
}

long play_audio_buffer_impl(void* audio_service_data, unsigned char *buffer, long length, long long ts)
{
//	printf("play_audio_buffer_impl \n");

	return [(audio_service_impl *)(audio_service_data) play_audio_buffer:buffer withLength:length withTs:ts];
}

long empty_audio_buffer_impl(void* audio_service_data)
{
//	printf("empty_audio_buffer_impl \n");

	return [(audio_service_impl *)(audio_service_data) empty_buffer_queue];
}

long replay_impl(void* audio_service_data)
{
//	printf("replay_impl \n");

	return [(audio_service_impl *)(audio_service_data) replay];
}
long pause_impl(void* audio_service_data)
{
//	printf("pause_impl \n");

	return [(audio_service_impl *)(audio_service_data) pause];
}

long set_play_speed_impl(void* audio_service_data, float play_speed)
{
//	printf("set_play_speed_impl play_speed = %f\n",play_speed);
	
	return [(audio_service_impl *)(audio_service_data) set_play_speed: play_speed];

//	return [(audio_service_impl *)(audio_service_data) pause];
}


long init_audio_service_impl()
{
//	g_context = NULL;
//	g_device = NULL;

//	printf("init_audio_service_impl in g_device = %d,g_context = %d\n",g_device,g_context);
	// 初始化设备
	g_device = alcOpenDevice(NULL);
	if (NULL == g_device)
	{
//		printf("cannot open device...\n");
		return 1;
	}
	
	// 创建设备context
	g_context = alcCreateContext(g_device, NULL);
	if (NULL == g_context)
	{
//		printf("cannot open context...\n");
		return 1;
	}
	alcMakeContextCurrent(g_context);
//	printf("init_audio_service_impl g_device = %d,g_context = %d\n",g_device,g_context);
	return 0;
}

long uninit_audio_service_impl()
{
//	printf("uninit_audio_service_impl in g_device = %d,g_context = %d\n",g_device,g_context);
	alcMakeContextCurrent(NULL);
//	printf("uninit_audio_service_impl g_device = %d,g_context = %d\n",g_device,g_context);
	if (NULL != g_context)
	{
//		printf("uninit_audio_service_impl alcDestroyContext g_context = %d\n",g_context);
		alcDestroyContext(g_context);
		g_context = NULL;
	}
	
	if (NULL != g_device)
	{
//		printf("uninit_audio_service_impl alcCloseDevice g_device = %d\n",g_device);
		alcCloseDevice(g_device);
		g_device = NULL;		
	}

	return 0;
}

// ---------------------------------------------------------------------
